package com.wcs.exam.controller.admin.biz;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wcs.exam.common.base.BaseBiz;
import com.wcs.exam.common.base.Result;
import com.wcs.exam.common.enums.CategoryTypeEnum;
import com.wcs.exam.common.util.BeanUtil;
import com.wcs.exam.controller.admin.req.*;
import com.wcs.exam.controller.admin.resp.AdminCategoryListResp;
import com.wcs.exam.controller.admin.resp.AdminCategoryViewResp;
import com.wcs.exam.dao.CategoryDao;
import com.wcs.exam.dao.impl.mapper.entity.Category;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Admin-分类
 *
 * @author wcs
 * @since 2025-03-11
 */
@Component
@RequiredArgsConstructor
public class AdminCategoryBiz extends BaseBiz {

    @NotNull
    private final CategoryDao dao;

    /**
     * 分类-列出
     *
     * @param req 分类-列出查询参数
     * @return 分类
     */
    public Result<List<AdminCategoryListResp>> list(AdminCategoryListReq req) {
        // 处理查询条件
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Category::getCategoryType, req.getCategoryType());
        wrapper.eq(ObjectUtil.isNotEmpty(req.getStatus()), Category::getStatus, req.getStatus());
        // 排序
        wrapper.orderByAsc(Category::getSort).orderByDesc(Category::getId);
        List<Category> categoryList = dao.list(wrapper);
        return Result.success(filter(0L, categoryList));
    }

    /**
     * 根据父级分类ID递归过滤并构建分类树
     *
     * @param parentId     父级分类ID（根节点传默认父ID）
     * @param categoryList 原始分类列表
     * @return 包含层级结构的分类树
     */
    private List<AdminCategoryListResp> filter(Long parentId, List<Category> categoryList) {
        if (CollectionUtil.isNotEmpty(categoryList)) {
            List<Category> list = categoryList.stream().filter(item -> parentId.compareTo(item.getParentId()) == 0).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(list)) {
                List<AdminCategoryListResp> respList = BeanUtil.copyProperties(list, AdminCategoryListResp.class);
                for (AdminCategoryListResp resp : respList) {
                    resp.setChildren(filter(resp.getId(), categoryList));
                }
                return respList;
            }
        }
        return null;
    }

    /**
     * 分类-添加
     *
     * @param req 分类
     * @return 添加结果
     */
    public Result<String> save(AdminCategorySaveReq req) {
        Category category = BeanUtil.copyProperties(req, Category.class);

        if (ObjectUtil.isNotNull(req.getParentId()) && req.getParentId() != 0L) {
            Category parentCategory = dao.getById(req.getParentId());
            if (ObjectUtil.isNull(parentCategory)) {
                return Result.error("父级分类不存在");
            }
            category.setCategoryType(parentCategory.getCategoryType());
        } else {
            if (ObjectUtil.isNull(req.getCategoryType())) {
                return Result.error("类型不能为空");
            }
            CategoryTypeEnum categoryTypeEnum = CategoryTypeEnum.byCode(req.getCategoryType());
            if (ObjectUtil.isNull(categoryTypeEnum)) {
                return Result.error("类型错误");
            }
        }

        boolean saveRes = dao.save(category);
        return saveRes ? Result.success(toI18nSuccess()) : Result.error(toI18nFail());
    }

    /**
     * 分类-查看
     *
     * @param id 主键ID
     * @return 分类
     */
    public Result<AdminCategoryViewResp> view(Long id) {
        Category category = dao.getById(id);
        if (ObjectUtil.isNull(category)) {
            return Result.error("分类不存在");
        }
        return Result.success(BeanUtil.copyProperties(category, AdminCategoryViewResp.class));
    }

    /**
     * 分类-编辑
     *
     * @param req 分类-编辑对象
     * @return 编辑结果
     */
    public Result<String> edit(AdminCategoryEditReq req) {
        // 获取校验分类
        Category category = dao.getById(req.getId());
        if (ObjectUtil.isNull(category)) {
            return Result.error("分类不存在");
        }

        // 更新分类
        Category updateCategory = BeanUtil.copyProperties(req, Category.class);
        updateCategory.setGmtCreate(null);
        updateCategory.setGmtModified(null);
        boolean updateRes = dao.updateById(updateCategory);
        return updateRes ? Result.success(toI18nSuccess()) : Result.error(toI18nFail());
    }

    /**
     * 分类-更新状态
     *
     * @param req 分类-更新状态对象
     * @return 更新状态结果
     */
    public Result<String> updateStatus(AdminCategoryUpdateStatusReq req) {
        // 获取校验分类
        Category category = dao.getById(req.getId());
        if (ObjectUtil.isNull(category)) {
            return Result.error("分类不存在");
        }

        // 更新分类
        Category updateCategory = BeanUtil.copyProperties(req, Category.class);
        updateCategory.setGmtCreate(null);
        updateCategory.setGmtModified(null);
        boolean updateRes = dao.updateById(updateCategory);
        return updateRes ? Result.success(toI18nSuccess()) : Result.error(toI18nFail());
    }

    /**
     * 分类-排序
     *
     * @param reqs 分类-排序对象
     * @return 排序结果
     */
    public Result<String> sort(List<AdminCategorySortReq> reqs) {
        // 查询获取分类
        List<Category> categoryList = dao
                .lambdaQuery()
                .in(Category::getId, reqs.stream().map(AdminCategorySortReq::getId).collect(Collectors.toSet()))
                .list();
        if (CollectionUtil.isEmpty(categoryList)) {
            return Result.success(toI18nSuccess());
        }


        // 处理待更新排序的分类
        List<Category> updateList = new ArrayList<>();
        handleSort(0L, reqs, updateList);

        // 批量更新分类排序
        if (CollectionUtil.isNotEmpty(updateList)) {
            dao.updateBatchById(updateList);
        }
        return Result.success(toI18nSuccess());
    }

    /**
     * 递归处理分类排序信息，将排序后的分类对象添加到categoryList中。
     *
     * @param parentId        父分类的ID
     * @param reqs            包含排序信息的分类请求列表
     * @param categoryList    用于收集更新后的分类对象的列表
     */
    private void handleSort(Long parentId, List<AdminCategorySortReq> reqs, List<Category> categoryList) {
        int sort = 1;
        // 遍历每个分类请求，设置排序值并添加到结果列表
        for (AdminCategorySortReq req : reqs) {
            Category updateCategory = new Category();
            updateCategory.setId(req.getId());
            updateCategory.setParentId(parentId);
            updateCategory.setSort(sort++);
            categoryList.add(updateCategory);
            // 递归处理子分类，将当前分类ID作为父ID
            if (CollectionUtil.isNotEmpty(req.getChildren())) {
                handleSort(req.getId(), req.getChildren(), categoryList);
            }
        }
    }


    /**
     * 分类-删除
     *
     * @param id ID主键
     * @return 删除结果
     */
    public Result<String> delete(Long id) {
        // 获取指定ID的分类对象，并校验其是否存在
        Category category = dao.getById(id);
        if (ObjectUtil.isNull(category)) {
            return Result.error("分类不存在");
        }

        // 检查是否存在以当前分类为父分类的下级分类
        boolean exists = dao.lambdaQuery().eq(Category::getParentId, id).exists();
        if (exists) {
            return Result.error("删除失败，存在下级分类");
        }

        // 执行删除操作，并根据删除结果返回相应的响应信息
        boolean deleteRes = dao.removeById(id);
        return deleteRes ? Result.success(toI18nSuccess()) : Result.error(toI18nFail());
    }
}
